package cn.fz.utils;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.crypto.asymmetric.SM2;
import lombok.Getter;
import org.bouncycastle.crypto.engines.SM2Engine;

import java.nio.charset.StandardCharsets;

public class SM2Demo02 {
    // 生成SM2公私钥对，并设置密文数据顺序为老标准 C1C2C3
    public static KeyPair generateSM2KeyPair() {
        SM2 sm2 = new SM2();
        // 设置密文数据顺序为老标准 C1C2C3
        // sm2.setCipher('C', '1', 'C', '2', 'C', '3');
        sm2.setMode(SM2Engine.Mode.C1C2C3);

        // 获取公钥和私钥
        String privateKey = sm2.getPrivateKeyBase64();
        String publicKey = sm2.getPublicKeyBase64();

        return new KeyPair(publicKey, privateKey);
    }

    // 用于存储公私钥对的简单结构
    // @NoArgsConstructor
    @Getter
    public static class KeyPair {
        private final String publicKey;
        private final String privateKey;

        public KeyPair(String publicKey, String privateKey) {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

    }

    public static String SM2Signature(String data, String priKey) {
        // SM2 sm2 = new SM2(ByteUtils.fromHexString(priKey), null);
        // byte[] sign = sm2.sign(data.getBytes(CharsetUtil.CHARSET_UTF_8));
        // return Base64Encoder.encode(sign);

        // 解码Base64编码的私钥为字节数组
        byte[] priKeyBytes = Base64Decoder.decode(priKey);

        // 使用解码后的私钥初始化SM2对象
        SM2 sm2 = new SM2(priKeyBytes, null);

        // 对数据进行签名，并将签名结果Base64编码
        byte[] sign = sm2.sign(data.getBytes(StandardCharsets.UTF_8));
        return Base64Encoder.encode(sign);
    }

    /**
     * 公钥验签
     */
    public static boolean SM2SigVerifier(String data, String sig, String pubKey) {
        // SM2 sm2 = new SM2(null, ByteUtils.fromHexString(pubKey));
        // byte[] decode = Base64Decoder.decode(sig);
        // return sm2.verify(data.getBytes(CharsetUtil.CHARSET_UTF_8), decode);

        // 解码Base64编码的公钥为字节数组
        byte[] pubKeyBytes = Base64Decoder.decode(pubKey);

        // 使用解码后的公钥初始化SM2对象
        SM2 sm2 = new SM2(null, pubKeyBytes);

        // 验证签名
        byte[] decode = Base64Decoder.decode(sig);
        return sm2.verify(data.getBytes(StandardCharsets.UTF_8), decode);
    }

    public static void main(String[] args) {
        KeyPair keyPair = generateSM2KeyPair();
        System.out.println("SM2公钥：" + keyPair.getPublicKey());
        System.out.println("SM2私钥：" + keyPair.getPrivateKey());
        String data = "Hello";
        String signature = SM2Signature(data, keyPair.getPrivateKey());
        System.out.println("SM2签名：" + signature);
        boolean isVerify = SM2SigVerifier(data, signature, keyPair.getPublicKey());
        System.out.println("SM2验签：" + isVerify);
    }
}
